local g = vim.g
local o = vim.o
local fn = vim.fn
local cmd = vim.cmd
local remap = vim.api.nvim_set_keymap
local keymap = vim.keymap.set
local autocmd = vim.api.nvim_create_autocmd
local autogroup = vim.api.nvim_create_augroup

g.loaded_python_provider = 0
g.loaded_python3_provider = 0
g.loaded_ruby_provider = 0
g.loaded_perl_provider = 0

g.mapleader = " "
g.maplocalleader = ","

local indent = 2
o.shiftwidth = indent
o.tabstop = indent
o.number = true
o.relativenumber = true
o.clipboard = 'unnamedplus'
o.foldenable = true
o.foldlevel = 99
o.foldlevelstart = 99
vim.opt.diffopt:append("linematch:50")
vim.opt.signcolumn = "yes"
vim.opt.updatetime = 300
o.guifont = "Operator Mono Lig,VictorMono Nerd Font Mono:h16"

vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" })
vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" })
vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" })
vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" })
vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" })
vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" })
vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" })

if g.neovide then
	g.neovide_input_macos_option_key_is_meta = "only_left"
	g.neovide_remember_window_size = true
	g.neovide_hide_mouse_when_typing = false
	g.neovide_window_blurred = true
	g.neovide_scroll_animation_far_lines = 1

	-- fix neovide input
	local function set_ime(args)
		if args.event:match("Enter$") then
			vim.g.neovide_input_ime = true
		else
			vim.g.neovide_input_ime = false
		end
	end

	local ime_input = vim.api.nvim_create_augroup("ime_input", { clear = true })

	vim.api.nvim_create_autocmd({ "InsertEnter", "InsertLeave" }, {
		group = ime_input,
		pattern = "*",
		callback = set_ime
	})

	vim.api.nvim_create_autocmd({ "CmdlineEnter", "CmdlineLeave" }, {
		group = ime_input,
		pattern = "[/\\?]",
		callback = set_ime
	})
end

cmd([[
  filetype plugin on
  filetype indent on
]])

vim.filetype.add({
	extension = {
		["http"] = "http",
	},
})

-- https://github.com/rockerBOO/awesome-neovim
-- https://github.com/glepnir/nvim-lua-guide-zh
-- https://github.com/neovim/neovim/wiki/Related-projects#Plugins
-- https://github.com/yutkat/my-neovim-pluginlist
-- https://github.com/LazyVim/LazyVim
-- using :source % or :luafile %
-- log: nvim -V9myNvim.log
-- remoe ^M: :%s/\r$//g
local function echo(str)
	vim.cmd("redraw")
	vim.api.nvim_echo({ { str, "Bold" } }, true, {})
end
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
	echo("Welcome to LEE   Installing lazy.nvim & plugins ...")
	fn.system({
		"git",
		"clone",
		"--filter=blob:none",
		"--single-branch",
		"https://github.com/folke/lazy.nvim.git",
		lazypath,
	})
end
vim.opt.runtimepath:prepend(lazypath)
require("lazy").setup({
	"pteroctopus/faster.nvim",
	{ "nvim-lua/plenary.nvim", "nvim-lua/popup.nvim", event = "VeryLazy" },
	{
		"echasnovski/mini.basics",
		event = "VeryLazy",
		version = false,
		dependencies = {
			"echasnovski/mini.comment",
			"echasnovski/mini.cursorword",
			"echasnovski/mini.move",
			"echasnovski/mini.align",
		},
		config = function()
			require("mini.basics").setup()
			require("mini.comment").setup()
			require("mini.cursorword").setup()
			require("mini.move").setup()
			require("mini.align").setup()
		end
	},
	{
		"folke/snacks.nvim",
		priority = 1000,
		lazy = false,
		opts = {
			quickfile = { enabled = true },
			lazygit = { enabled = true },
			rename = { enabled = true },
			toggle = { enabled = true },
			words = { enabled = true },
			profiler = { enabled = true },
			dim = { enabled = true },
			indent = {
				enabled = true,
				hl = {
					"RainbowRed",
					"RainbowYellow",
					"RainbowBlue",
					"RainbowOrange",
					"RainbowGreen",
					"RainbowViolet",
					"RainbowCyan",
				}
			},
			zen = { enabled = true },
		},
		keys = {
			{ "<leader>un",        function() Snacks.notifier.hide() end,           desc = "Dismiss All Notifications" },
			{ "<leader>bd",        function() Snacks.bufdelete() end,               desc = "Delete Buffer" },
			{ "<leader><leader>g", function() Snacks.lazygit() end,                 desc = "Lazygit" },
			{ "<leader>gB",        function() Snacks.gitbrowse() end,               desc = "Git Browse" },
			{ "<leader>gf",        function() Snacks.lazygit.log_file() end,        desc = "Lazygit Current File History" },
			{ "<leader>cR",        function() Snacks.rename.rename_file() end,      desc = "Rename File" },
			{ "]]",                function() Snacks.words.jump(vim.v.count1) end,  desc = "Next Reference",              mode = { "n", "t" } },
			{ "[[",                function() Snacks.words.jump(-vim.v.count1) end, desc = "Prev Reference",              mode = { "n", "t" } },
			{ "<leader>ps",        function() Snacks.profiler.scratch() end,        desc = "Profiler Scratch Buffer" },
			{ "<leader>tl",        function() Snacks.dim() end,                     desc = "Focus on the active scope" },
		},
		init = function()
			vim.api.nvim_create_autocmd("User", {
				pattern = "VeryLazy",
				callback = function()
					_G.dd = function(...)
						Snacks.debug.inspect(...)
					end
					_G.bt = function()
						Snacks.debug.backtrace()
					end
					vim.print = _G.dd -- Override print to use snacks for `:=` command

					Snacks.toggle.option("spell", { name = "Spelling" }):map("<leader>us")
					Snacks.toggle.option("wrap", { name = "Wrap" }):map("<leader>uw")
					Snacks.toggle.option("relativenumber", { name = "Relative Number" }):map("<leader>uL")
					Snacks.toggle.line_number():map("<leader>ul")
					Snacks.toggle.option("conceallevel", { off = 0, on = vim.o.conceallevel > 0 and vim.o.conceallevel or 2 }):map(
						"<leader>uc")
					Snacks.toggle.treesitter():map("<leader>uT")
					Snacks.toggle.option("background", { off = "light", on = "dark", name = "Dark Background" }):map("<leader>ub")
					Snacks.toggle.profiler():map("<leader>pp")
					Snacks.toggle.profiler_highlights():map("<leader>ph")
				end,
			})

			local prev = { new_name = "", old_name = "" } -- Prevents duplicate events
			vim.api.nvim_create_autocmd("User", {
				pattern = "NvimTreeSetup",
				callback = function()
					local events = require("nvim-tree.api").events
					events.subscribe(events.Event.NodeRenamed, function(data)
						if prev.new_name ~= data.new_name or prev.old_name ~= data.old_name then
							data = data
							Snacks.rename.on_rename_file(data.old_name, data.new_name)
						end
					end)
				end,
			})
		end,
	},
	{
		"rcarriga/nvim-notify",
		event = "VeryLazy",
		opts = {
			render = "minimal",
			stages = "static",
			top_down = false,
			timeout = 1000,
			background_colour = "#000000",
		}
	},
	-- 状态栏
	{
		"romgrk/barbar.nvim",
		event = "VeryLazy",
		config = function()
			require("bufferline").setup({
				animation = true,
				auto_hide = true,
				icons = { buffer_index = true, filetype = { enabled = true } },
			})
		end,
	},
	{
		"nvim-tree/nvim-web-devicons",
		lazy = true,
		config = function()
			require("nvim-web-devicons").setup({ color_icons = true, default = true })
		end,
	},
	{
		"nvim-lualine/lualine.nvim",
		event = "VimEnter",
		config = function()
			require("modules.lualine")
		end,
	},
	{
		"kyazdani42/nvim-tree.lua",
		cmd = "NvimTreeToggle",
		config = function()
			require("modules.nvim-tree")
		end,
	},
	{ "goolord/alpha-nvim",    event = "VimEnter" },
	-- git相关
	{
		"tpope/vim-fugitive",
		event = "VeryLazy",
		dependencies = {
			"tpope/vim-rhubarb",
		},
	},
	{
		"akinsho/git-conflict.nvim",
		event = "VeryLazy",
		config = true,
	},
	{ "rbong/vim-flog",     cmd = { "Flog" } },
	{
		"sindrets/diffview.nvim",
		cmd = { "DiffviewOpen", "DiffviewToggleFiles", "DiffviewFocusFiles" },
		config = true,
	},
	{
		"lewis6991/gitsigns.nvim",
		event = "BufRead",
		config = function()
			require("modules.gitsigns")
		end,
	},
	-- 语法高亮
	{
		"kevinhwang91/nvim-treesitter",
		event = "VeryLazy",
		build = ":TSUpdate",
		config = function()
			require("modules.treesitter")
		end,
	},
	{
		"brenoprata10/nvim-highlight-colors",
		event = "VeryLazy",
		config = true,
	},
	-- theme 主题 -- https://vimcolorschemes.com/
	{ "RRethy/nvim-base16", event = "VeryLazy" },
	{
		"craftzdog/solarized-osaka.nvim",
		lazy = true,
		priority = 1000,
		opts = {
			transparent = true,
		}
	},
	{ "mg979/vim-visual-multi",    event = "VeryLazy" },
	{ "terryma/vim-expand-region", event = "VeryLazy" },
	{
		"smoka7/hop.nvim",
		version = "*",
		opts = {},
		cmd = { "HopWord", "HopLine", "HopPattern" },
		config = true,
	},
	-- {
	-- 	"ibhagwan/fzf-lua",
	-- 	config = function()
	-- 		require('fzf-lua').setup({ 'fzf-native' })
	-- 	end,
	-- },
	{
		"nvim-telescope/telescope.nvim",
		event = "VeryLazy",
		dependencies = {
			"nvim-telescope/telescope-live-grep-args.nvim",
			{ "nvim-telescope/telescope-fzf-native.nvim", build = "make" },
			"nvim-telescope/telescope-file-browser.nvim",
			"nvim-telescope/telescope-symbols.nvim",
			"aaronhallaert/advanced-git-search.nvim",
			"debugloop/telescope-undo.nvim",
			"piersolenski/telescope-import.nvim",
		},
		config = function()
			require("modules.telescope")
		end,
	},
	-- {
	-- 	"renerocksai/telekasten.nvim",
	-- 	event = "VeryLazy",
	-- 	dependencies = {
	-- 		"renerocksai/calendar-vim",
	-- 		"mzlogin/vim-markdown-toc",
	-- 	},
	-- 	config = function()
	-- 		require("modules.telekasten")
	-- 	end,
	-- }, -- 日志管理
	-- 语法建议
	{
		"neovim/nvim-lspconfig",
		event = { "BufReadPre", "BufNewFile" },
		opts = {
			inlay_hints = {
				enabled = true,
			},
		},
		dependencies = {
			{
				"folke/neoconf.nvim",
				cmd = "Neoconf",
				opts = {},
			},
			"williamboman/mason.nvim",
			"williamboman/mason-lspconfig.nvim",
			"b0o/schemastore.nvim",
			{
				"nvimdev/lspsaga.nvim",
				event = { "LspAttach" },
				branch = "main",
				config = function()
					require("modules.saga")
				end,
			},
			{
				"folke/lazydev.nvim",
				ft = "lua",
				cmd = "LazyDev",
				opts = {
					library = {
						{ path = "luvit-meta/library", words = { "vim%.uv" } },
						{ path = "snacks.nvim",        words = { "Snacks" } },
					},
				},
			},
			{ "Bilal2453/luvit-meta", lazy = true },
		},
		config = function()
			require("lsp/config")
		end,
	},
	-- {
	-- 	"zeioth/garbage-day.nvim",
	-- 	event = "VeryLazy",
	-- 	opts = {}
	-- },
	{
		"Bekaboo/dropbar.nvim",
		event = "VeryLazy",
		opts = {},
	},
	{
		"https://git.sr.ht/~whynothugo/lsp_lines.nvim",
		event = "LspAttach",
		config = function()
			require("lsp_lines").setup()
			keymap("", "<Leader>tp", require("lsp_lines").toggle, { desc = "Toggle lsp_lines" })
		end,
	},
	-- {
	-- 	"rachartier/tiny-inline-diagnostic.nvim",
	-- 	event = "LspAttach",
	-- 	priority = 1000,
	-- 	config = function()
	-- 		require('tiny-inline-diagnostic').setup({
	-- 			preset = "modern",
	-- 		})
	-- 	end
	-- },
	{
		"pmizio/typescript-tools.nvim",
		event = "VeryLazy",
		ft = { "typescript", "typescriptreact", "javascript" },
		config = function()
			require("modules.typescript-tools")
		end,
	},
	{
		"dmmulroy/tsc.nvim",
		ft = { "typescript", "typescriptreact" },
		event = { "LspAttach" },
		config = true,
	},
	-- 语法提示
	{
		"hrsh7th/nvim-cmp",
		event = { "InsertEnter", "CmdlineEnter" },
		dependencies = {
			"hrsh7th/cmp-nvim-lsp",
			"petertriho/cmp-git",
			"hrsh7th/cmp-buffer",
			"hrsh7th/cmp-path",
			"hrsh7th/cmp-cmdline",
			"hrsh7th/cmp-calc",
			"hrsh7th/cmp-emoji",
			"roginfarrer/cmp-css-variables",
			"xzbdmw/colorful-menu.nvim",

			{
				"onsails/lspkind.nvim",
				event = "InsertEnter",
				lazy = true,
			},
			{
				"luckasRanarison/tailwind-tools.nvim",
				name = "tailwind-tools",
				build = ":UpdateRemotePlugins",
				opts = {},
			},
			{
				"L3MON4D3/LuaSnip",
				dependencies = "rafamadriz/friendly-snippets",
				version = "v2.*",
				build = "make install_jsregexp",
				config = function()
					require("modules.luasnip")
				end,
			},
			-- {
			-- 	"supermaven-inc/supermaven-nvim",
			-- 	config = function()
			-- 		require("supermaven-nvim").setup({
			-- 			disable_inline_completion = true,
			-- 			disable_keymaps = true,
			-- 		})
			-- 	end,
			-- },
			-- {
			-- 	"jcdickinson/codeium.nvim",
			-- 	event = "InsertEnter",
			-- 	lazy = true,
			-- 	config = function()
			-- 		require("codeium").setup({ enable_chat = true, enable_cmp_source = false })
			-- 	end,
			-- },
			{
				"dnlhc/glance.nvim",
				event = { "LspAttach" },
				config = function()
					require("glance").setup()
				end,
			},
			{
				"aznhe21/actions-preview.nvim",
				event = { "LspAttach" },
				config = function()
					keymap({ "v", "n" }, "gm", require("actions-preview").code_actions)
				end,
			},
		},
		config = function()
			require("modules.cmp")
		end,
	},
	-- {
	-- 	"stevearc/conform.nvim",
	-- 	event = { "BufWritePre" },
	-- 	cmd = { "ConformInfo" },
	-- 	opts = {
	-- 		formatters_by_ft = {
	-- 			markdown = { "autocorrect" }, -- brew install autocorrect
	-- 			javascript = { "prettierd" },
	-- 			typescript = { "prettierd" },
	-- 			tsx = { "prettierd", "stylelint" },
	-- 			css = { "prettierd", "stylelint" },
	-- 			scss = { "prettierd", "stylelint" },
	-- 			javascriptreact = { "prettierd", "stylelint" },
	-- 			typescriptreact = { "prettierd", "stylelint" },
	-- 		},
	-- 		-- format_on_save = { timeout_ms = 500, lsp_fallback = true },
	-- 		format_on_save = false,
	-- 		formatters = {},
	-- 	},
	-- 	init = function()
	-- 		vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"
	-- 	end,
	-- },
	{
		"luozhiya/fittencode.nvim",
		event = { "InsertEnter" },
		opts = {
			use_default_keymaps = false,
			inline_completion = {
				enabled = false
			},
			keymaps = {
				inline = {
					["<C-j>"] = "accept_all_suggestions",
					["<C-Down>"] = "accept_line",
					["<C-Right>"] = "accept_word",
					["<C-Up>"] = "revoke_line",
					["<C-Left>"] = "revoke_word",
					["<A-\\>"] = "triggering_completion",
				},
				chat = {
					["q"] = "close",
					["[c"] = "goto_previous_conversation",
					["]c"] = "goto_next_conversation",
					["c"] = "copy_conversation",
					["C"] = "copy_all_conversations",
					["d"] = "delete_conversation",
					["D"] = "delete_all_conversations",
				},
			},
		},
	},
	{
		"MeanderingProgrammer/render-markdown.nvim",
		opts = {
			file_types = { "markdown", "Avante", "codecompanion" },
			latex = { enabled = false }
		},
		ft = { "markdown", "Avante", "codecompanion" },
	},
	{
		"yetone/avante.nvim",
		event = "VeryLazy",
		version = false,
		opts = {
			provider = "openai",
			vendors = {
				groq = {
					__inherited_from = "openai",
					api_key_name = "GROQ_API_KEY",
					endpoint = "https://api.groq.com/openai/v1",
					model = "llama-3.1-70b-versatile",
				},
				xai = {
					__inherited_from = "openai",
					api_key_name = "XAI_API_KEY",
					endpoint = "https://api.x.ai/v1",
					model = "grok-2-1212",
				},
				codestral = {
					__inherited_from = "openai",
					api_key_name = "CODESTRAL_API_KEY",
					endpoint = "https://codestral.mistral.ai/v1",
					model = "codestral-latest",
				},
				deepseek = {
					__inherited_from = "openai",
					api_key_name = "DEEPSEEK_API_KEY",
					endpoint = "https://api.deepseek.com",
					model = "deepseek-coder",
				},
				siliconflow = {
					__inherited_from = "openai",
					api_key_name = "SILICONFLOW_API_KEY",
					endpoint = "https://api.siliconflow.cn/v1",
					model = "Qwen/QwQ-32B-Preview",
				},
				google = {
					__inherited_from = "openai",
					api_key_name = "OPENROUTER_API_KEY",
					endpoint = "https://openrouter.ai/api/v1",
					model = "google/gemini-2.0-flash-thinking-exp:free",
				},
			},
			openai = {
				api_key_name = "OPENROUTER_API_KEY",
				endpoint = "https://openrouter.ai/api/v1",
				model = "anthropic/claude-3.5-sonnet:beta",
			},
		},
		build = "make",
		dependencies = {
			"stevearc/dressing.nvim",
			"MunifTanjim/nui.nvim",
			{
				"HakonHarnes/img-clip.nvim",
				event = "VeryLazy",
				opts = {
					default = {
						embed_image_as_base64 = false,
						prompt_for_file_name = false,
						drag_and_drop = {
							insert_mode = true,
						},
					},
				},
			},
		},
	},
	{
		"olimorris/codecompanion.nvim",
		event = "VeryLazy",
		config = function()
			require("modules.codecompanion")
		end,
	},
	-- {
	-- 	"GeorgesAlkhouri/nvim-aider",
	-- 	cmd = {
	-- 		"AiderTerminalToggle",
	-- 	},
	-- 	keys = {
	-- 		{ "<leader>a/", "<cmd>AiderTerminalToggle<cr>",   desc = "Open Aider" },
	-- 		{ "<leader>as", "<cmd>AiderTerminalSend<cr>",     desc = "Send to Aider",        mode = { "n", "v" } },
	-- 		{ "<leader>ac", "<cmd>AiderQuickSendCommand<cr>", desc = "Send Command To Aider" },
	-- 		{ "<leader>ab", "<cmd>AiderQuickSendBuffer<cr>",  desc = "Send Buffer To Aider" },
	-- 		{ "<leader>a+", "<cmd>AiderQuickAddFile<cr>",     desc = "Add File to Aider" },
	-- 		{ "<leader>a-", "<cmd>AiderQuickDropFile<cr>",    desc = "Drop File from Aider" },
	-- 	},
	-- 	config = true,
	-- },
	-- {
	-- 	"sourcegraph/sg.nvim",
	-- 	event = "VeryLazy",
	-- },
	-- {
	-- 	"ThePrimeagen/refactoring.nvim",
	-- 	event = "InsertEnter",
	-- 	ft = { "typescript", "typescriptreact" },
	-- 	config = true,
	-- },
	{
		"folke/trouble.nvim",
		ft = "qf",
		event = { "LspAttach" },
		config = true,
	},
	-- {
	-- 	"rcarriga/nvim-dap-ui",
	-- 	cmd = "DapOpen",
	-- 	dependencies = { "mfussenegger/nvim-dap" },
	-- 	config = function()
	-- 		require("modules.dap")
	-- 	end,
	-- },
	-- rust
	{
		"mrcjkb/rustaceanvim",
		version = "^5", -- Recommended
		lazy = false,
		ft = { "rust" }, -- try pr2502/ra-multiplex
		config = function()
			g.rustaceanvim = {
				server = {
					on_attach = function(client)
						client.server_capabilities.semanticTokensProvider = nil
						if vim.lsp.inlay_hint then
							vim.lsp.inlay_hint.enable(true)
						end
					end,
				},
			}
		end,
	},
	{
		"Saecki/crates.nvim",
		event = "BufRead Cargo.toml",
		config = true,
	},
	{
		"David-Kunz/cmp-npm",
		event = "BufRead package.json",
		config = true,
	},
	{
		"vuki656/package-info.nvim",
		event = "BufRead package.json",
		config = function()
			require("package-info").setup({ package_manager = "pnpm" })
		end,
	},
	-- { "lervag/vimtex",          ft = "tex" },
	{
		"mistweaverco/kulala.nvim",
		ft = "http",
		opts = {},
	},
	{ "pechorin/any-jump.vim",      cmd = { "AnyJump", "AnyJumpVisual", "AnyJumpBack" } },
	-- { "metakirby5/codi.vim", cmd = { "Codi" } },
	{
		"0x100101/lab.nvim",
		ft = { "javascript", "typescript" },
		build = "cd js && npm ci",
		opts = {},
	},
	-- {
	--   "jmbuhr/otter.nvim",
	--   ft = "markdown",
	--   event = "VeryLazy",
	--   opts = {},
	-- },
	{ "tpope/vim-dispatch",         cmd = { "Make", "Dispatch", "Focus", "Start" } },
	{ "skywind3000/asyncrun.vim",   cmd = "AsyncRun" },
	{ "skywind3000/asynctasks.vim", cmd = "AsyncTask" },
	--- 方便操作
	{
		"nacro90/numb.nvim",
		event = "VeryLazy",
		config = true,
	},
	{ "voldikss/vim-translator", cmd = { "Translate" } }, -- npm install fanyi -g 安装翻译
	{
		"barrett-ruth/import-cost.nvim",
		event = "VeryLazy",
		build = "sh install.sh pnpm",
		config = true,
	},
	{ "machakann/vim-sandwich",  event = "VeryLazy" },
	{
		"windwp/nvim-autopairs",
		event = "InsertEnter",
		config = true,
	},
	{
		"chentoast/marks.nvim",
		event = "VeryLazy",
		dependencies = {
			{
				"toppair/reach.nvim",
				config = function()
					require("reach").setup({ notifications = true })
				end,
			},
		},
		config = function()
			require("modules.marks")
		end,
	},
	{
		"folke/which-key.nvim",
		event = "VeryLazy",
		config = true,
	}, -- 提示leader按键
	{ "nvchad/volt",                     lazy = true },
	{
		"nvchad/minty",
		cmd = { "Shades", "Huefy" },
		opts = { huefy = { border = false } }
	},
	{
		"nvchad/menu",
		lazy = true,
	},
	{ "nvchad/showkeys",                 cmd = "ShowkeysToggle" },
	{ "nvchad/timerly",                  cmd = "TimerlyToggle" },
	{ "HiPhish/rainbow-delimiters.nvim", event = "VeryLazy" }, -- 彩虹匹配
	{ "windwp/nvim-ts-autotag",          event = "VeryLazy" },
	{ "AndrewRadev/tagalong.vim",        event = "VeryLazy" },
	{
		"folke/todo-comments.nvim",
		event = "VeryLazy",
		config = function()
			require("modules.todo")
		end,
	},
	{ "ntpeters/vim-better-whitespace", event = "VeryLazy" },
	{ "dhruvasagar/vim-table-mode",     event = "VeryLazy", ft = { "markdown" } },
	{
		"max397574/better-escape.nvim",
		event = "VeryLazy",
		opts = {
			default_mappings = false,
			mappings = {
				i = {
					j = {
						k = "<Esc>",
						j = "<Esc>",
					},
				},
				c = {
					j = {
						k = "<Esc>",
						j = "<Esc>",
					},
				},
				t = {
					j = {
						k = "<C-\\><C-n>",
					},
				},
				s = {
					j = {
						k = "<Esc>",
					},
				},
			},
		}
	},
	{ "ThePrimeagen/vim-be-good", cmd = "VimBeGood" },
	{ "tpope/vim-repeat",         event = "VeryLazy" },
	{ "nvim-pack/nvim-spectre",   event = "VeryLazy" },
	{ "wakatime/vim-wakatime",    event = "VeryLazy" },
	{
		"gennaro-tedesco/nvim-jqx",
		event = { "BufReadPost" },
		ft = { "json", "yaml" },
	},
	{
		"ckolkey/ts-node-action",
		event = "VeryLazy",
		dependencies = {
			"nvim-treesitter",
		},
		config = true,
	}, -- 字符组合切换
	{ "akinsho/toggleterm.nvim", version = "*", config = true, event = "VeryLazy" },
	{
		"folke/noice.nvim",
		event = "VimEnter",
		config = function()
			require("modules.noice")
		end,
		dependencies = {
			"MunifTanjim/nui.nvim",
			"rcarriga/nvim-notify",
		},
	},
	{
		"petertriho/nvim-scrollbar",
		event = "VeryLazy",
		config = true,
	},
	{
		"mvllow/modes.nvim",
		event = "VeryLazy",
		tag = "v0.2.0",
		config = true,
	},
}, {
	rocks = {
		enabled = false,
		hererocks = false,
	},
	performance = {
		rtp = {
			disabled_plugins = {
				"gzip",
				"netrwPlugin",
				"tarPlugin",
				"tohtml",
				"tutor",
				"zipPlugin",
			},
		},
	},
})

autocmd("FileType", {
	pattern = {
		"lazy",
	},
	callback = function(event)
		vim.bo[event.buf].buflisted = false
		keymap("n", "<Esc>", "<cmd>close<cr>", { buffer = event.buf, silent = true })
	end,
})

--mappings
local function map(mode, lhs, rhs)
	local options = { noremap = true }
	remap(mode, lhs, rhs, options)
end

-- map("v", "x", "d")
-- map("v", "d", '"_d')
map("n", "P", '"0p')
map("v", "P", '"0p')
map("n", ";f", "<C-f>")
map("n", ";b", "<C-b>")
map("n", ";", ":")  --semicolon to enter command mode
map("n", "j", "gj") --move by visual line not actual line
map("n", "k", "gk")
map("n", "q", "<cmd>q<CR>")
map("n", "gw", "<cmd>HopWord<CR>") --easymotion/hop
map("n", "gl", "<cmd>HopLine<CR>")
map("n", "g/", "<cmd>HopPattern<CR>")
map("n", "<leader>:", "<cmd>terminal<CR>")
remap("n", "<esc>", "<cmd>noh<CR><CR>", { noremap = true, silent = true })

map("n", "<leader>m", "<cmd>ReachOpen marks<CR>")

-- -- lua fzf
-- map("n", "<leader>*", "<cmd>FzfLua<CR>") --fuzzy
-- map("n", "<leader>f", "<cmd>FzfLua files<CR>")
-- map("n", "<leader>b", "<cmd>FzfLua buffers<CR>")
-- -- map("n", "<leader>m", "<cmd>FzfLua marks<CR>")
-- map("n", "<leader>/", "<cmd>FzfLua live_grep_native<CR>")
-- map("n", "<leader>'", "<cmd>FzfLua resume<CR>")
-- map("n", "gs", "<cmd>FzfLua grep_cword<CR>")
-- map("n", "fg", "<cmd>FzfLua git_files<CR>")
-- map("n", "fc", "<cmd>FzfLua commands<CR>")
-- map("n", "fm", "<cmd>FzfLua git_status<CR>")
-- telescope
map("n", "<leader>*", "<cmd>Telescope<CR>") --fuzzy
map("n", "ft", "<cmd>Telescope treesitter<CR>")
map("n", "fc", "<cmd>Telescope commands<CR>")
map("n", "fe", "<cmd>Telescope file_browser<CR>")
map("n", "fm", "<cmd>Telescope git_status<CR>")
map("n", "<leader>f", "<cmd>Telescope find_files<CR>")
map("n", "<leader>b", "<cmd>Telescope buffers<CR>")
-- map("n", "<leader>m", "<cmd>Telescope marks<CR>")
-- map('n', '<leader>/', '<cmd>Telescope live_grep<CR>')
map("n", "<leader>'", "<cmd>Telescope resume<CR>")
map("n", "gs", "<cmd>Telescope grep_string<CR>")
map("n", "fg", "<cmd>Telescope git_files<CR>")
map("n", "gq", "<cmd>Telescope diagnostics<CR>")
map("n", "gQ", '<cmd>lua require"telescope.builtin".symbols{ sources = {"emoji", "kaomoji", "gitmoji"} }<CR>')

-- -- telekasten
-- map("n", "<leader>zf", '<cmd>lua require("telekasten").find_notes()<CR>')
-- map("n", "<leader>zd", '<cmd>lua require("telekasten").find_daily_notes()<CR>')
-- map("n", "<leader>zg", '<cmd>lua require("telekasten").search_notes()<CR>')
-- map("n", "<leader>zz", '<cmd>lua require("telekasten").follow_link()<CR>')
-- map("n", "<leader>zT", '<cmd>lua require("telekasten").goto_today()<CR>')
-- map("n", "<leader>zw", '<cmd>lua require("telekasten").find_weekly_notes()<CR>')
-- map("n", "<leader>zn", '<cmd>lua require("telekasten").new_note()<CR>')
-- map("n", "<leader>zc", '<cmd>lua require("telekasten").show_calendar()<CR>')
-- map("n", "<leader>zC", "<cmd>CalendarT<CR>")
-- map("n", "<leader>zt", '<cmd>lua require("telekasten").toggle_todo()<CR>')
-- map("n", "<leader>za", '<cmd>lua require("telekasten").show_tags()<CR>')

map("n", "<leader>ns", '<cmd>lua require("package-info").show()<CR>')
map("n", "<leader>np", '<cmd>lua require("package-info").change_version()<CR>')
map("n", "<leader>ni", '<cmd>lua require("package-info").install()<CR>')

map("n", "<leader>ct", '<cmd>lua require("crates").toggle()<CR>')
map("n", "<leader>cv", '<cmd>lua require("crates").show_versions_popup()<CR>')

map("n", "<leader>e", "<cmd>NvimTreeToggle<CR>")
map("n", "<C-n>", "<cmd>NvimTreeToggle<CR>")
map("n", "<leader>tr", "<cmd>NvimTreeRefresh<CR>")
--
map("n", "<leader>tw", "<cmd>Translate<CR>")
map("n", "<leader>th", "<cmd>TSToggle highlight<CR>")
-- diffview
map("n", "<leader>td", "<cmd>DiffviewOpen<CR>")
map("n", "<leader>tD", "<cmd>DiffviewClose<CR>")
-- wincmd
map("n", "<c-k>", "<cmd>wincmd k<CR>") --ctrlhjkl to navigate splits
map("n", "<c-j>", "<cmd>wincmd j<CR>")
map("n", "<c-h>", "<cmd>wincmd h<CR>")
map("n", "<c-l>", "<cmd>wincmd l<CR>")
map("n", "<c-s>", "<cmd>w<CR>")
-- barbar
map("n", "<s-q>", "<cmd>BufferClose<CR>")
map("n", "<Tab>", "<cmd>BufferNext<CR>")
map("n", "<s-Tab>", "<cmd>BufferPrevious<CR>")
-- map('n', 'gb', '<cmd>BufferPick<CR>')
-- map('n', 'gp', '<cmd>bprevious<CR>')
-- map('n', '<leader>be', '<cmd>tabedit<CR>')
-- git
map("n", "<leader>ga", "<cmd>Git add %:p<CR>")
map("n", "<leader>go", "<cmd>Git add .<CR>")
map("n", "<leader>gm", "<cmd>Git commit<CR>")
map("n", "<leader>gs", "<cmd>Git status<CR>")
map("n", "<leader>gl", "<cmd>Git pull<CR>")
map("n", "<leader>gu", "<cmd>Git push<CR>")
map("n", "<leader>gr", "<cmd>Git reset --hard<CR>")
-- map('n', '<leader>gl', '<cmd>Git log<CR>')

-- refactoring
-- map("v", "<leader>re", '<cmd>lua require("refactoring").refactor("Extract Function")<CR>')
-- map("v", "<leader>rf", '<cmd>lua require("refactoring").refactor("Extract Function To File")<CR>')
-- map("v", "<leader>rv", '<cmd>lua require("refactoring").refactor("Extract Variable")<CR>')
-- map("v", "<leader>ri", '<cmd>lua require("refactoring").refactor("Inline Variable")<CR>')
-- map("n", "<leader>ri", '<cmd>lua require("refactoring").refactor("Inline Variable")<CR>')
-- map("n", "<leader>rr", '<cmd><Esc><cmd>lua require("telescope").extensions.refactoring.refactors()<CR>')

map("n", "<leader>j", "<cmd>AnyJump<CR>")
map("v", "<leader>j", "<cmd>AnyJumpVisual<CR>")
map("n", "<leader>ab", "<cmd>AnyJumpBack<CR>")
map("n", "<leader>al", "<cmd>AnyJumpLastResults<CR>")

-- ufo
map("n", "zR", '<cmd>lua require("ufo").openAllFolds()<CR>')
map("n", "zM", '<cmd>lua require("ufo").closeAllFolds()<CR>')

-- LSP
map("n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>")
map("n", "gD", "<cmd>lua vim.lsp.buf.declaration()<CR>")
-- map("n", "<leader>q", "<cmd>lua vim.diagnostic.setloclist()<CR>")
map("n", "gr", "<cmd>lua vim.lsp.buf.references()<CR>")
map("n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>")
map("n", "<leader>wa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>")
map("n", "<leader>wr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>")
map("n", "<leader>wl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>")
map("n", "<leader>F", "<cmd>lua vim.lsp.buf.format({ async = true })<CR>")

-- map("n", "ga", "<cmd>lua vim.lsp.buf.code_action()<CR>")
-- map("n", "K", "<cmd>lua vim.lsp.buf.hover()<CR>")
-- map("n", "gn", "<cmd>lua vim.lsp.buf.rename()<CR>")
-- map("n", "<leader>D", "<cmd>lua vim.lsp.buf.type_definition()<CR>")
-- map("n", "[d", "<cmd>lua vim.diagnostic.goto_prev()<CR>")
-- map("n", "]d", "<cmd>lua vim.diagnostic.goto_next()<CR>")

map("n", "gp", "<cmd>Lspsaga peek_definition<CR>")
map("n", "ga", "<cmd>Lspsaga code_action<CR>")
map("x", "gA", "<cmd>Lspsaga range_code_action<CR>")
map("n", "K", "<cmd>Lspsaga hover_doc<CR>")
map("n", "gn", "<cmd>Lspsaga rename<CR>")
map("n", "gt", "<cmd>Lspsaga peek_type_definition<CR>")
map("n", "gi", "<cmd>Lspsaga finder<CR>")
map("n", "gC", "<cmd>Lspsaga show_cursor_diagnostics<CR>")
map("n", "ge", "<cmd>Lspsaga show_line_diagnostics<CR>")
map("n", "]d", "<cmd>Lspsaga diagnostic_jump_next<CR>")
map("n", "[d", "<cmd>Lspsaga diagnostic_jump_prev<CR>")
map("n", "<leader>ts", "<cmd>Lspsaga outline<CR>")

map("n", "<leader>q", "<cmd>Trouble diagnostics toggle<CR>")

-- typescript-tools
map("n", "gj", "<cmd>TSToolsGoToSourceDefinition<CR>")

keymap({ "n" }, "gK", require("ts-node-action").node_action, { desc = "Trigger Node Action" })

-- Spectre
keymap('n', '<leader>S', '<cmd>lua require("spectre").toggle()<CR>', {
	desc = "Toggle Spectre"
})
keymap('n', '<leader>sw', '<cmd>lua require("spectre").open_visual({select_word=true})<CR>', {
	desc = "Search current word"
})
keymap('v', '<leader>sw', '<esc><cmd>lua require("spectre").open_visual()<CR>', {
	desc = "Search current word"
})
keymap('n', '<leader>sp', '<cmd>lua require("spectre").open_file_search({select_word=true})<CR>', {
	desc = "Search on current file"
})

-- map("n", "<leader>cr", "<cmd>Rest run<CR>")

-- keymap({ "n" }, "<Leader>cl", require("kulala").run(), { desc = "Trigger HTTP Action" })

-- Codi
-- map("n", "<leader>ce", "<Cmd>CodiExpand<CR>")

-- vim-project
-- map("n", "<leader>pl", "<Cmd>ProjectList<CR>")
-- map("n", "<leader>pf", "<Cmd>ProjectFindInFiles<CR>")

map("n", "<A-i>", "<cmd>ToggleTerm direction=float<CR>")
map("t", "<A-i>", "<C-\\><C-n><cmd>ToggleTermToggleAll<CR>")
if g.neovide then
	map("n", "<C-i>", "<cmd>ToggleTerm direction=float<CR>")
	map("t", "<C-i>", "<C-\\><C-n><cmd>ToggleTermToggleAll<CR>")
end

cmd([[autocmd BufWritePre * %s/\s\+$//e]]) --remove trailing whitespaces
cmd([[autocmd BufWritePre * %s/\n\+\%$//e]])

autocmd({ "TextYankPost" }, {
	pattern = "*",
	callback = function()
		vim.highlight.on_yank({ higrou = "IncSearch", timeout = 500 })
	end,
	desc = "Highlight yanked text",
	group = autogroup("highlight_yank", { clear = true }),
})

-- Smart Number
autocmd("InsertEnter", {
	command = "set norelativenumber",
	pattern = "*",
})
autocmd("InsertLeave", {
	command = "set relativenumber",
	pattern = "*",
})

autocmd("WinLeave", {
	pattern = "*",
	command = "set nocursorline",
})
autocmd("WinEnter", {
	pattern = "*",
	command = "set cursorline",
})

-- Disable fold in Outline
autocmd("FileType", {
	pattern = "Outline",
	callback = function()
		vim.opt_local.foldcolumn = "0"
		vim.opt_local.stc = ""
	end,
})

vim.api.nvim_create_augroup("Random", { clear = true })

autocmd("VimResized", {
	group = "Random",
	desc = "Keep windows equally resized",
	command = "tabdo wincmd =",
})

autocmd("TermOpen", {
	group = "Random",
	command = "setlocal nonumber norelativenumber signcolumn=no",
})

local numbers = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }
for _, num in pairs(numbers) do
	map("n", "<leader>" .. num, "<cmd>BufferGoto " .. num .. "<CR>")
end
map("n", "<leader>0", "<cmd>BufferGoto 10<CR>")

g.css_variables_files = { "variables.css" }

g.markdown_fenced_language = {
	"ts=typescript",
}
g.markdown_fenced_languages =
{ "javascript", "typescript", "bash", "lua", "go", "rust", "c", "cpp", "html", "scss", "css" }

--theme
cmd("colorscheme solarized-osaka")

-- vim-better-whitespace
g.better_whitespace_filetypes_blacklist = { "diff", "git", "qf", "help", "fugitive", "minimap" }

-- Vimtex config
-- vim.g.vimtex_quickfix_mode = 2
-- vim.g.vimtex_compiler_latexmk_engines = { ["_"] = "-lualatex -shell-escape" }
-- vim.g.vimtex_indent_on_ampersands = 0
-- vim.g.vimtex_view_method = "sioyek"
-- vim.g.matchup_override_vimtex = 1

-- Other settings
vim.g.latexindent_opt = "-m" -- for neoformat, I use latexindent

local startify = require("alpha.themes.startify")
local header = {
	"┍━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┑",
	"│ ⣇⣿⠘⣿⣿⣿⡿⡿⣟⣟⢟⢟⢝⠵⡝⣿⡿⢂⣼⣿⣷⣌⠩⡫⡻⣝⠹⢿⣿⣷ │",
	"│ ⡆⣿⣆⠱⣝⡵⣝⢅⠙⣿⢕⢕⢕⢕⢝⣥⢒⠅⣿⣿⣿⡿⣳⣌⠪⡪⣡⢑⢝⣇ │",
	"│ ⡆⣿⣿⣦⠹⣳⣳⣕⢅⠈⢗⢕⢕⢕⢕⢕⢈⢆⠟⠋⠉⠁⠉⠉⠁⠈⠼⢐⢕⢽ │",
	"│ ⡗⢰⣶⣶⣦⣝⢝⢕⢕⠅⡆⢕⢕⢕⢕⢕⣴⠏⣠⡶⠛⡉⡉⡛⢶⣦⡀⠐⣕⢕ │",
	"│ ⡝⡄⢻⢟⣿⣿⣷⣕⣕⣅⣿⣔⣕⣵⣵⣿⣿⢠⣿⢠⣮⡈⣌⠨⠅⠹⣷⡀⢱⢕ │",
	"│ ⡝⡵⠟⠈⢀⣀⣀⡀⠉⢿⣿⣿⣿⣿⣿⣿⣿⣼⣿⢈⡋⠴⢿⡟⣡⡇⣿⡇⡀⢕ │",
	"│ ⡝⠁⣠⣾⠟⡉⡉⡉⠻⣦⣻⣿⣿⣿⣿⣿⣿⣿⣿⣧⠸⣿⣦⣥⣿⡇⡿⣰⢗⢄ │",
	"│ ⠁⢰⣿⡏⣴⣌⠈⣌⠡⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣬⣉⣉⣁⣄⢖⢕⢕⢕ │",
	"│ ⡀⢻⣿⡇⢙⠁⠴⢿⡟⣡⡆⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣵⣵⣿ │",
	"│ ⡻⣄⣻⣿⣌⠘⢿⣷⣥⣿⠇⣿⣿⣿⣿⣿⣿⠛⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ │",
	"│ ⣷⢄⠻⣿⣟⠿⠦⠍⠉⣡⣾⣿⣿⣿⣿⣿⣿⢸⣿⣦⠙⣿⣿⣿⣿⣿⣿⣿⣿⠟ │",
	"│ ⡕⡑⣑⣈⣻⢗⢟⢞⢝⣻⣿⣿⣿⣿⣿⣿⣿⠸⣿⠿⠃⣿⣿⣿⣿⣿⣿⡿⠁⣠ │",
	"│ ⡝⡵⡈⢟⢕⢕⢕⢕⣵⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣶⣿⣿⣿⣿⣿⠿⠋⣀⣈⠙ │",
	"│ ⡝⡵⡕⡀⠑⠳⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⢉⡠⡲⡫⡪⡪⡣ │",
	"┕━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┙",
	"+--------------------------------+",
	"|  Love You, 盼盼和小璇同学❤❤❤   |",
	"+----------------+---------------+",
}

-- 布局
startify.section.header.val = header

require("alpha").setup(startify.opts)

-- 布局
startify.section.header.val = header

require("alpha").setup(startify.opts)

cmd([[ let @r="\y:%s/\<C-r>\"//g\<Left>\<Left>" ]])
cmd([[ let @h=":ProjectRoot \<CR> :w\<CR> :vsp | terminal  go run *.go \<CR>i" ]])
cmd([[ let @1=":call CppComp() \<CR>G:66\<CR>" ]])
cmd([[ let @c=":cd %:h \<CR>" ]])
-- 按 @g 运行代码
-- All previous macros have been changed to autocmd, @g macro will run current file
cmd([[
	augroup run_file
		autocmd BufEnter *.java let @g=":w\<CR>:vsp | terminal java %\<CR>i"
		autocmd BufEnter *.py let @g=":w\<CR>:vsp |terminal python %\<CR>i"
		autocmd BufEnter *.asm let @g=":w\<CR> :!nasm -f elf64 -o out.o % && ld out.o -o a.out \<CR> | :vsp |terminal ./a.out\<CR>i"
		autocmd BufEnter *.cpp let @g=":w\<CR> :!g++ %\<CR> | :vsp |terminal ./a.out\<CR>i"
		autocmd BufEnter *.c let @g=":w\<CR> :!gcc %\<CR> | :vsp |terminal ./a.out\<CR>i"
		autocmd BufEnter *.go let @g=":w\<CR> :vsp | terminal go run % \<CR>i"
		autocmd BufEnter *.js let @g=":w\<CR> :vsp | terminal node % \<CR>i"
		autocmd BufEnter *.html let @g=":w\<CR> :silent !chromium % \<CR>"
	augroup end
]])

cmd([[
  highlight Normal ctermbg=NONE guibg=NONE
  hi default link HlSearchNear IncSearch
  hi default link HlSearchLens WildMenu
  hi default link HlSearchLensNear IncSearch
  hi default link HlSearchFloat IncSearch
  highlight MarkSignHL guifg=#E06C75
  highlight MarkSignNumHL guifg=#E5C07B
  highlight MarkVirtTextHL guifg=#98C379
  hi tkLink ctermfg=72 guifg=#689d6a cterm=bold,underline gui=bold,underline
  hi tkBrackets ctermfg=gray guifg=gray
  hi tkHighlight ctermbg=214 ctermfg=124 cterm=bold guibg=#fabd2f guifg=#9d0006 gui=bold
  hi link CalNavi CalRuler
  hi tkTagSep ctermfg=gray guifg=gray
  hi tkTag ctermfg=175 guifg=#d3869B
  highlight link LspSagaFinderSelection Search
]])

-- function SpellToggle()
-- 	if vim.opt.spell:get() then
-- 		vim.opt_local.spell = false
-- 		vim.opt_local.spelllang = "en"
-- 	else
-- 		vim.opt_local.spell = true
-- 		vim.opt_local.spelllang = { "en_us" }
-- 	end
-- end

-- keymap("n", "<leader>5", ":lua SpellToggle()<cr>")
-- keymap("n", "<leader>z", "[s1z=``")

-- require("modules.beacon") -- Beacon to show cursor
-- require("modules.cmdline");           -- Beacon to show cursor
-- require("modules.terminal_bg_sync") -- Background sync for Termux
-- vim.api.nvim_create_user_command("FixWhitespace", [[%s/\s\+$//e]], {})
-- keymap("n", "<leader>3", ":retab<cr>:FixWhitespace<cr>")

-- menu
keymap("n", "<RightMouse>", function()
	vim.cmd.exec '"normal! \\<RightMouse>"'

	local options = vim.bo.ft == "NvimTree" and "nvimtree" or "default"
	require("menu").open(options, { mouse = true })
end, {})

-- keymap("n", "gm", function()
-- 	local options = vim.bo.ft == "NvimTree" and "nvimtree" or "default"
-- 	require("menu").open(options, { mouse = false })
-- end, { desc = "Menu: toggle action menus" })
